#!/usr/bin/env python
# encoding: utf-8
"""
@author: youfeng
@email: youfeng243@163.com
@license: Apache Licence
@file: proxy_handler_.py
@time: 2017/12/20 10:19
"""

# 代理管理对象
import random
import threading
import time

import requests

from config.proxy_conf import DYNAMIC_PROXY_CONF, STATIC_PROXY_URL


# 代理使用总入口
class ProxyHandler(object):
    # 单例
    __instance = None

    # 更新线程句柄
    static_update_thread = None

    def __init__(self, dynamic_proxy_conf=None,
                 static_proxy_url=None,
                 log=None):

        self.log = log

        self.log.info("初始化代理信息...")

        # 动态静态配置信息
        self.dynamic_proxy_conf = dynamic_proxy_conf if dynamic_proxy_conf is not None else DYNAMIC_PROXY_CONF
        self.static_proxy_url = static_proxy_url if static_proxy_url is not None else STATIC_PROXY_URL

        # 管理现在可用的静态代理
        self.static_point = 0
        self.static_length = 0
        self.static_proxy_list = []

        # 静态代理更新线程
        self.static_update_thread = threading.Thread(target=self.static_update_run, )
        self.static_update_thread.setDaemon(True)
        self.static_update_thread.start()

        self.log.info("代理初始化完成...")

    # 更新静态代理
    def update_static_proxy(self):

        for _ in xrange(3):
            proxy_list = []
            try:
                r = requests.get(self.static_proxy_url, timeout=10)
                if r is None or r.status_code != 200:
                    self.log.error("更新静态代理网络异常...")
                    continue

                line_list = r.text.strip().split('\n')
                for line in line_list:
                    line = line.strip().strip("\r").strip("\n")
                    if len(line) <= 0:
                        continue

                    proxy = {'http': 'http://' + line}
                    if '7777' in line:
                        new_line = line.replace('7777', '55555')
                        proxy['http'] = 'socks5://' + new_line
                    elif '8088' in line:
                        new_line = line.replace('8088', '1088')
                        proxy['http'] = 'socks5://' + new_line

                    proxy_list.append(proxy)
                self.log.info('从远端更新代理成功....')
                return proxy_list
            except Exception as e:
                self.log.error('访问静态代理链接异常: ')
                self.log.exception(e)
        return []

    # 静态代理更新线程
    def static_update_run(self):
        self.log.info("启动静态代理更新线程...")

        while True:
            # 更新静态代理
            static_proxy_list = self.update_static_proxy()

            static_proxy_length = len(static_proxy_list)
            if static_proxy_length > 0:
                self.static_proxy_list = static_proxy_list
                self.static_length = static_proxy_length
                self.log.info("更新静态代理完成: static_length = {}".format(self.static_length))

            self.log.info("完成静态代理更新, 休眠3600秒")

            # 每隔1个小时更新一次
            time.sleep(3600)

    # 获得代理接口
    def get_random_proxy(self, host):
        proxy_type = random.choice([0, 1])

        if proxy_type == 0 and self.static_length > 0:
            proxy = self.__get_static_proxy()
            if len(proxy) > 0:
                return proxy
            return self.__get_dynamic_proxy(host)

        proxy = self.__get_dynamic_proxy(host)
        if len(proxy) > 0:
            return proxy
        return self.__get_static_proxy()

    # 获取代理
    def __get_dynamic_proxy(self, host):
        for _ in xrange(3):
            try:
                r = requests.get('http://{}:{}/proxy/{}'.format(
                    self.dynamic_proxy_conf['host'],
                    self.dynamic_proxy_conf['port'],
                    host),
                    timeout=10)
                if r is None or r.status_code != 200 or 'failed' in r.text or 'False' in r.text:
                    time.sleep(1)
                    self.log.warn("动态代理服务异常, 重试...")
                    continue

                self.log.info('鲲鹏 ip = {ip}'.format(ip=r.text))
                proxies = {'http': 'http://{host}'.format(host=r.text)}
                return proxies
            except Exception as e:
                self.log.error("动态代理访问异常:")
                self.log.exception(e)
                time.sleep(1)
        return {}

    # 获取静态代理
    def __get_static_proxy(self):
        if self.static_point >= self.static_length:
            self.static_point = 0

        try:
            if self.static_length > 0:
                proxy = self.static_proxy_list[self.static_point]
                self.static_point += 1
                self.log.info('静态代理 ip = {}'.format(proxy))
                return proxy

            self.log.error("当前静态代理长度为空: static_length = {} actual length = {}".format(
                self.static_length, len(self.static_proxy_list)))
            self.static_length = len(self.static_proxy_list)
        except Exception as e:
            self.log.error("静态代理取址失败: point = {} cur length = {} actual length = {}".format(
                self.static_point, self.static_length, len(self.static_proxy_list)))
            self.log.exception(e)
            return {}

        return {}